import {
	split_index,
	count_front
} from '@/config/dlt-config';
import DltApi from './DltApi';
import FsDriver from './FsDriver';

const fsDriver = new FsDriver();
const dltApi = new DltApi();

/**
 * 数据源模型类
 * @version 1.0.5
 */
class DltDataModel {

	/**
	 * 缓存键名
	 */
	cacheKeyOfDataSource = 'dlt-data-source';
	cacheKeyOfRefreshTime = 'dlt-refresh-time';
	cacheKeyOfActiveDrawNum = 'dlt-active-draw-num';


	/**
	 * 设置数据源
	 * @param {Array} rows 
	 */
	setDataSource(list) {
		// 增量添加
		let data = JSON.parse(fsDriver.get(this.cacheKeyOfDataSource) ?? '[]');
		if (data.length > 0 && (list[list.length - 1].lotteryDrawNum < data[0].lotteryDrawNum)) {
			data.unshift(...list.filter(row => row.lotteryDrawNum > data[0].lotteryDrawNum));
			if (data.length > 100) {
				data = data.slice(0, 100);
			}
		} else {
			data = list;
		}
		fsDriver.save(this.cacheKeyOfDataSource, JSON.stringify(data));
		// console.log('【DltDataSource数据库】setDataSource ', data);
	}

	/**
	 * 返回数据源
	 * @param {String} activeDrawNum 本期期号
	 * @param {Number} offset 偏移量，无需修改
	 * @returns {Array} 示例：[{lotteryDrawNum: "25066", lotteryDrawResult: "15 18 27 28 34 03 06", lotteryDrawTime: "2025-06-14"}, ...]
	 */
	getDataSource(activeDrawNum = '', offset = 1) {
		let dataset = JSON.parse(fsDriver.get(this.cacheKeyOfDataSource) ?? '[]');
		if (activeDrawNum) {
			let pos = dataset.findIndex(v => v.lotteryDrawNum == activeDrawNum);
			if (pos > -1) {
				return dataset.slice(pos + offset);
			}
		}
		return dataset;
	}

	getLastRecord() {
		let dataset = this.getDataSource();
		return dataset.length > 0 ? dataset[dataset.length - 1] : {};
	}

	/**
	 * 设置时光机期号
	 * @param {Number} num 
	 */
	setActiveDrawNum(num) {
		fsDriver.save(this.cacheKeyOfActiveDrawNum, num);
	}

	/**
	 * 获取时光机期号
	 * @returns {String} 返回期号
	 */
	getActiveDrawNum() {
		return fsDriver.get(this.cacheKeyOfActiveDrawNum) || '';
	}

	/**
	 * 设置刷新时间
	 */
	setRefreshTime() {
		let refreshTime = new Date().getTime();
		fsDriver.save(this.cacheKeyOfRefreshTime, refreshTime);
	}

	getRefreshTime(isLocalString = false) {
		let refreshTime = parseInt(fsDriver.get(this.cacheKeyOfRefreshTime) ?? '0');
		console.log('refreshTime', refreshTime);
		if (isLocalString && refreshTime > 0) {
			// 返回本地存储的时间字符串
			let date = new Date(refreshTime);
			let info = {
				Y: date.getFullYear(),
				m: ('0' + (date.getMonth() + 1)).slice(-2),
				d: ('0' + date.getDate()).slice(-2),
				H: ('0' + date.getHours()).slice(-2),
				i: ('0' + date.getMinutes()).slice(-2),
				s: ('0' + date.getSeconds()).slice(-2),
				w: date.getDay(),
				ww: ['日', '一', '二', '三', '四', '五', '六'][date.getDay()],
			}
			return `${info.Y}-${info.m}-${info.d} 周${info.ww} ${info.H}:${info.i}:${info.s}`;
		}
		return refreshTime;
	}

	/**
	 * 检测刷新时间是否过期
	 * @param {Number} time 秒
	 * @returns Boolean 如果超过指定时间，则返回 true，表示需要刷新数据
	 */
	isExpire(time = 7200) {
		return (new Date().getTime() - this.getRefreshTime(false)) > (time * 1000);
	}

	/**
	 * 返回指定号数的列数据
	 * @param {Array} data 数据
	 * @param {Number} columnIdx 号数列索引（从 0 到 6）
	 * @param {Boolean} isLocation 是否是位置数据
	 * @returns {Array}
	 */
	getColumnData(data, columnIdx, isLocation = false) {
		// const data = getDataSource();
		if (isLocation) {
			let inc = columnIdx < split_index ? 0 : count_front;
			// 返回位置数据，前 5 列是红球，后 2 列是蓝球
			return data.map((row, i) => {
				return [i, parseInt(row.lotteryDrawResult.split(' ')[columnIdx]) + inc];
			});
		}
		return data.map(row => row.lotteryDrawResult.split(' ')[columnIdx]);
	}

	/**
	 * 获取每个号码的出现次数统计。包含全部号码（前后区）统计和每个号数列（1-7）的统计
	 * @param {Array} dataset 数据源，默认为当前数据源
	 * @returns Object {statAll, statColumns}
	 * @version 1.0.1
	 */
	getDrawalStat(dataset) {
		if (!dataset) {
			dataset = this.getDataSource();
		}
		let statConsecutiveNums = [{}, {}]; // 连号统计，front/back
		let arrTemp = [],
			arrTemp2 = [];
		let totalCount = dataset.length;
		let statColumns = [{}, {}, {}, {}, {}, {}, {}]; // 1...7
		let statAll = [{}, {}]; // front/back
		let pos = 0; // 是否是前区号码
		dataset.forEach((row, rowIdx) => {
			row.lotteryDrawResult.split(' ').forEach((num, i) => {
				pos = i < split_index ? 0 : 1;
				statAll[pos][num] = statAll[pos][num] ? statAll[pos][num] + 1 : 1;
				statColumns[i][num] = statColumns[i][num] ? statColumns[i][num] + 1 : 1;
			});
			if (rowIdx < 50 && dataset[rowIdx - 1]) {
				arrTemp = [
					row.lotteryDrawResult.split(' ').slice(0, split_index),
					row.lotteryDrawResult.split(' ').slice(split_index)
				];
				arrTemp2 = [
					dataset[rowIdx - 1].lotteryDrawResult.split(' ').slice(0, split_index),
					dataset[rowIdx - 1].lotteryDrawResult.split(' ').slice(split_index)
				];
				pos = 0;
				while (pos <= 1) {
					arrTemp[pos].filter(v => arrTemp2[pos].includes(v)).forEach((num, i) => {
						if (!statConsecutiveNums[pos][num]) {
							statConsecutiveNums[pos][num] = rowIdx;
						}
					})
					pos++;
				}
			}

		});
		dataset = null;
		// 排序
		let statAllSorted = [{}, {}];
		let statConsecutiveNumsSorted = [{}, {}];
		for (let i = 0; i < 2; i++) {
			Object.keys(statAll[i]).sort().forEach(key => {
				statAllSorted[i]['N' + key] = statAll[i][key];
			});
			Object.keys(statConsecutiveNums[i]).sort().forEach(key => {
				statConsecutiveNumsSorted[i]['N' + key] = statConsecutiveNums[i][key];
			});
		}
		statAll = null;
		statConsecutiveNums = null;
		let statColumnsSorted = [],
			statSorted = {};
		statColumns.forEach((statObj, i) => {
			statSorted = {};
			Object.keys(statObj).sort().forEach(key => {
				statSorted['N' + key] = statObj[key];
			});
			statColumnsSorted[i] = statSorted;
		});
		statColumns = null;
		return {
			statAll: statAllSorted,
			statColumns: statColumnsSorted,
			statConsecutiveNums: statConsecutiveNumsSorted,
		};
	}

	/**
	 * 获取上期开奖号码包含的不可能连续开奖的号码
	 * @param {Object} statConsecutiveNums 连号统计信息
	 * @param {Object} prevDrawResult 上期开奖号码
	 * @return Array [[], []]
	 */
	getBlackNumsByPrevDrawResult(statConsecutiveNums, prevDrawResult) {
		console.log('statConsecutiveNums', statConsecutiveNums)
		if (!prevDrawResult || !statConsecutiveNums) {
			return [
				[],
				[]
			];
		}
		let tempArr = prevDrawResult.split(' ');
		let prevDrawResultArr = [tempArr.slice(0, split_index), tempArr.slice(split_index)];
		tempArr = [
			Object.keys(statConsecutiveNums[0]).map(v => v.substring(1)),
			Object.keys(statConsecutiveNums[1]).map(v => v.substring(1))
		];
		return [
			prevDrawResultArr[0].filter(v => !tempArr[0].includes(v)),
			prevDrawResultArr[1].filter(v => !tempArr[1].includes(v))
		];
	}

	/**
	 * 封装加载数据方法
	 * @param {Boolean} isClientForce 是否在客户端强制刷新数据。默认 false。
	 * @param {Boolean} isServerForce 是否在服务端强制刷新数据。默认 true。
	 * @param {Boolean} isOffifial 是否直接从彩票官方采集数据。默认 true。
	 * @returns resolve({rows, isLocalCache})
	 * @version 1.0.3
	 */
	loadData(isClientForce = false, isServerForce = true, isOffifial = true) {
		return new Promise((resolve, reject) => {
			let isLocalCache = false;
			if (isClientForce || this.isExpire() || this.getDataSource().length === 0) {
				console.log('【loadData】重新加载大乐透数据。刷新时间:', this.getRefreshTime(true));
				dltApi.fetchData(isServerForce, isOffifial).then(rows => {
					console.log('【loadData】加载大乐透远程数据成功');
					this.setRefreshTime();
					this.setDataSource(rows);
					isLocalCache = false;
					resolve({
						rows,
						isLocalCache
					});
				}).catch(err => {
					console.log('【loadData】加载大乐透数据错误', err);
					reject(err);
				});
			} else {
				console.log('【loadData】使用大乐透本地缓存数据。刷新时间:', this.getRefreshTime(true));
				isLocalCache = true;
				resolve({
					rows: this.getDataSource(),
					isLocalCache
				});
			}
		});
	}
}

export default DltDataModel;